package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.constant.pf.ScoringStatusConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dao.sys.excel.AutoExcelDao;
import com.plian.system.entity.im.BaseInvestmentExecution;
import com.plian.system.entity.pf.BaseAssessScore;
import com.plian.system.entity.pf.BaseOfficeScore;
import com.plian.system.entity.pf.EvaluationScoreDetail;
import com.plian.system.entity.sys.Office;
import com.plian.system.mapper.pf.BaseAssessScoreMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.im.IBaseInvestmentExecutionService;
import com.plian.system.service.pf.IBaseAssessScoreService;
import com.plian.system.service.pf.IBaseOfficeScoreService;
import com.plian.system.service.pf.IEvaluationScoreDetailService;
import com.plian.system.service.pf.IPerformanceScoreService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.office.IOfficeService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.pf.BaseAssessScoreVO;
import com.plian.system.vo.pf.ScoreMethodVO;
import com.plian.system.wrapper.pf.BaseAssessScoreWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * @Author: Take-off
 * @Description: TODO
 * @Date: 2023/1/29 7:07 PM
 * @Version: 1.0
 **/
@Slf4j
@Service
@AllArgsConstructor
public class BaseAssessScoreServiceImpl extends BaseServiceImpl<BaseAssessScoreMapper,BaseAssessScore> implements IBaseAssessScoreService, BaseFlowService {

    private FormWorkflowService formWorkflowService;

    private IFormCodeService formCodeService;

    private IEvaluationScoreDetailService evaluationScoreDetailService;

    private IOfficeService officeService;

    private BaseAssessScoreWrapper baseAssessScoreWrapper;

    private IPerformanceScoreService performanceScoreService;

    private IBaseOfficeScoreService baseOfficeScoreService;

    private AutoExcelDao autoExcelDao;

    private IBaseInvestmentExecutionService baseInvestmentExecutionService;

    @Override
    public boolean saveOrUpdate(BaseAssessScore baseAssessScore) {
        if (!Optional.ofNullable(baseAssessScore.getStatus()).isPresent()){
            if (!Optional.ofNullable(baseAssessScore.getEvaluationId()).isPresent()) {
                baseAssessScore.setStatus(FormStatusConstant.STASH);
            }else {
                baseAssessScore.setStatus(FormStatusConstant.UNREVIEWED);
            }
        }
        if (baseAssessScore.getStatus().equals(FormStatusConstant.REJECT)){
            baseAssessScore.setStatus(FormStatusConstant.UNREVIEWED);
        }

        if (!Optional.ofNullable(baseAssessScore.getId()).isPresent()) {
            baseAssessScore.setCode(formCodeService.getCode(FormTypeConstant.PF_BASE_ASSESS));
            baseAssessScore.setFormType(String.valueOf(FormTypeConstant.PF_BASE_ASSESS));
        }
        baseAssessScore.setScoreStatus(ScoringStatusConstant.FINAL_SCORE);
        return super.saveOrUpdate(baseAssessScore);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BaseAssessScore baseAssessScore = getById(id);
            if (baseAssessScore == null) {
                return false;
            } else if (baseAssessScore.getStatus() != null &&
                    (baseAssessScore.getStatus() != FormStatusConstant.STASH && baseAssessScore.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }

        boolean result = super.deleteLogic(ids);
        if (result){
            evaluationScoreDetailService.deleteByParentId(ids);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(BaseAssessScore baseAssessScore) {
        boolean result = saveOrUpdate(baseAssessScore);
        if (result) {
            Long officeId = baseAssessScore.getOfficeId();
            Office office = officeService.getById(officeId);
            List<EvaluationScoreDetail> evaluationScoreDetails = baseAssessScore.getEvaluationScoreDetails();
            if (CollectionUtil.isNotEmpty(evaluationScoreDetails)){
                for (EvaluationScoreDetail detail : evaluationScoreDetails){
                    if (detail.getId() != null &&
                            Optional.ofNullable(detail.getIsDeleted()).isPresent() && detail.getIsDeleted().intValue() == 1) {
                        evaluationScoreDetailService.removeById(detail.getId());
                    }else {
                        if (!Optional.ofNullable(detail.getBaseScoreId()).isPresent()){
                            detail.setBaseScoreId(baseAssessScore.getId());
                            detail.setFillingUnitId(officeId+"");
                            detail.setFillingUnitName(office.getName());
                        }
                        evaluationScoreDetailService.saveOrUpdate(detail);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public R<BaseAssessScoreVO> getDetailObj(BaseAssessScore baseAssessScore) {
        BaseAssessScoreVO baseAssessScoreVO = new BaseAssessScoreVO();
        Long baseId = baseAssessScore.getId();
        List<EvaluationScoreDetail> details = new ArrayList<>();
        if (Optional.ofNullable(baseId).isPresent()){
            baseAssessScore = getById(baseId);
            baseAssessScoreVO = baseAssessScoreWrapper.entityToVO(baseAssessScore);
            //评分细则
            List<EvaluationScoreDetail> scoreDetailList = evaluationScoreDetailService.list(new LambdaQueryWrapper<EvaluationScoreDetail>().eq(EvaluationScoreDetail::getBaseScoreId, baseAssessScore.getEvaluationId()));
            if (CollectionUtil.isNotEmpty(scoreDetailList)){
                details.addAll(scoreDetailList);
            }
            //责任处室评分
            List<EvaluationScoreDetail> detailList = baseOfficeScoreService.getAllDetailByOrg(baseAssessScore.getFillingUnitId());
            if (CollectionUtil.isNotEmpty(detailList)){
                details.addAll(detailList);
            }
            List<EvaluationScoreDetail> scoreDetails = evaluationScoreDetailService.list(new LambdaQueryWrapper<EvaluationScoreDetail>().eq(EvaluationScoreDetail::getBaseScoreId, baseId));
            if (CollectionUtil.isNotEmpty(scoreDetails)){
                details.addAll(scoreDetails);
            }
        }
        if (CollectionUtil.isNotEmpty(details)){
            //附件
            evaluationScoreDetailService.setFiles(details);
            baseAssessScoreVO.setEvaluationScoreDetails(details);
        }
        //考核评分办法
        List<ScoreMethodVO> allScoreMethod = performanceScoreService.getAllScoreMethod(baseAssessScore.getFillingYear());
        baseAssessScoreVO.setScoreMethodVOS(allScoreMethod);

        //放置跳转Id
        setJumpId(baseAssessScoreVO);
        return R.data(baseAssessScoreVO);
    }

    /**
     * @Author: Take-off
     * @Description: //TODO 放置跳转Id
     * @Date: 5:03 PM 2023/2/10
     * @Param: [assessScoreVO]
     * @return: void
     **/
    private void setJumpId(BaseAssessScoreVO assessScoreVO){
        //鉴证表Id
        PageData pageData = new PageData();
        pageData.put("orgId",assessScoreVO.getFillingUnitId());
        pageData.put("reportTime",assessScoreVO.getFillingYear() +"-01-01 00:00:00");
        try {
            List<PageData> list = autoExcelDao.findJianzhenList(pageData);
            if (CollectionUtil.isNotEmpty(list)){
                String id = list.get(0).getString("id");
                assessScoreVO.setTableId(id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //投资Id
        List<BaseInvestmentExecution> executionList = baseInvestmentExecutionService.list(new LambdaQueryWrapper<BaseInvestmentExecution>().like(BaseInvestmentExecution::getFilingMonth,assessScoreVO.getFillingYear())
                .eq(BaseInvestmentExecution::getFilingUnitId, assessScoreVO.getFillingUnitId()).eq(BaseInvestmentExecution::getStatus, 3).orderByDesc(BaseInvestmentExecution::getFilingMonth));
        if (CollectionUtil.isNotEmpty(executionList)){
            assessScoreVO.setInvestmentId(executionList.get(0).getId());
        }
        //是否都填写完成
        Boolean flag = updateFinishStatus(assessScoreVO);
        assessScoreVO.setFlag(flag);
    }

    /**
     * @Author: Take-off
     * @Description: //TODO 查询是否完成
     * @Date: 5:02 PM 2023/2/10
     * @Param: [baseOfficeScore]
     * @return: java.lang.Boolean
     **/
    private Boolean updateFinishStatus(BaseAssessScoreVO baseAssessScore){
        //是否所有处室都评分
        List<BaseOfficeScore> allOfficeScores = baseOfficeScoreService.list(new LambdaQueryWrapper<BaseOfficeScore>().eq(BaseOfficeScore::getFillingYear, baseAssessScore.getFillingYear()).eq(BaseOfficeScore::getFillingUnitId,baseAssessScore .getFillingUnitId()));
        Boolean flag = true;
        for (BaseOfficeScore officeScore:allOfficeScores){
            if (!(ScoringStatusConstant.OFFICE_SCORE_PROGRESS.equals(officeScore.getScoreStatus())
                    && officeScore.getStatus() == 3)){
                flag =false;
                break;
            }
        }
        return flag;
    }
    
    @Override
    public ListResult<BaseAssessScoreVO> list(Query query){
        List<SearchEntity> entityList = query.getSearch();
        if (query.getAscs()==null&&query.getDescs()==null){
            query.setDescs("create_time");
        }
        QueryWrapper<BaseAssessScore> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new BaseAssessScore()), entityList
        );

        IPage<BaseAssessScore> pages = page(Condition.getPage(query), queryWrapper);
        List<BaseAssessScoreVO> baseAssessScoreVOS = baseAssessScoreWrapper.entityToVO(pages.getRecords());

        ListResult<BaseAssessScoreVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(baseAssessScoreVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);
        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        Boolean result = handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
        //修改为已终评
        BaseAssessScore baseAssessScore = getById(id);
        baseAssessScore.setScoreStatus(ScoringStatusConstant.FINAL_SCORE_FINISH);
        updateById(baseAssessScore);
        return result;
    }

    @Override
    public Boolean reject(String id, int formState,String commont) {
        return handleStatus(Long.valueOf(id), formState);
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            BaseAssessScore baseAssessScore = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                baseAssessScore.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                baseAssessScore.setApprovedTime(now);
            }
            baseAssessScore.setStatus(updateStatus);
            updateById(baseAssessScore);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BaseAssessScore> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BaseAssessScore::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BaseAssessScore> baseAssessScores = list(queryWrapper);
        List<BaseAssessScoreVO> baseAssessScoreVOS = baseAssessScoreWrapper.entityToVO(baseAssessScores);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(baseAssessScoreVOS)){
                for (BaseAssessScoreVO vo : baseAssessScoreVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getFillingUnitName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getFillingUnitId());
                    pd.put("formType", FormTypeConstant.PF_BASE_ASSESS);
                    pd.put("orgName", vo.getFillingUnitName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.PF_BASE_ASSESS);
    }
}
